package top.whysu.rongcloud.service.impl;

import com.alibaba.fastjson.JSONObject;
import io.rong.models.Result;
import io.rong.models.group.GroupMember;
import io.rong.models.group.GroupModel;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import top.whysu.rongcloud.api.ImageUtil;
import top.whysu.rongcloud.api.dto.messages.GroupNtfMessage;
import top.whysu.rongcloud.api.dto.messages.groups.GroupsDismiss;
import top.whysu.rongcloud.api.dto.messages.groups.GroupsQuit;
import top.whysu.rongcloud.constant.CodeConstant;
import top.whysu.rongcloud.constant.ConfigConstant;
import top.whysu.rongcloud.constant.RongCloudConstant;
import top.whysu.rongcloud.dao.RongCloudGroupMemberDao;
import top.whysu.rongcloud.dao.RongCloudGroupsDao;
import top.whysu.rongcloud.dao.RongCloudUserDao;
import top.whysu.rongcloud.dto.rongcloud.groups.*;
import top.whysu.rongcloud.exception.BusinessException;
import top.whysu.rongcloud.fastdfs.FastDFSClientWrapper;
import top.whysu.rongcloud.po.RongCloudGroupMemberPO;
import top.whysu.rongcloud.po.RongCloudGroupsPO;
import top.whysu.rongcloud.po.RongCloudUserPO;
import top.whysu.rongcloud.service.RongCloudGroupMemberService;
import top.whysu.rongcloud.service.RongCloudGroupsService;
import top.whysu.rongcloud.util.CheckStringUtil;
import top.whysu.rongcloud.util.RongCloudUtil;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

@Service("RongCloudGroupsServiceImpl")
public class RongCloudGroupsServiceImpl implements RongCloudGroupsService {

    private static final Logger LOGGER = LoggerFactory.getLogger(RongCloudGroupsServiceImpl.class);

    @Resource
    RongCloudGroupsDao rongCloudGroupsDao;
    @Resource
    RongCloudGroupMemberDao rongCloudGroupMemberDao;
    @Resource
    RongCloudGroupMemberService rongCloudGroupMemberService;
    @Resource
    RongCloudUserDao rongCloudUserDao;
    /**
     * 融云API
     */
    private io.rong.RongCloud rongCloud = io.rong.RongCloud.getInstance(ConfigConstant.appKey, ConfigConstant.appSecret);
    @Resource
    private FastDFSClientWrapper dfsClient;

    @Value("${erongcloud.fileRoot}")
    private String fileRoot;

    @Override
    public RongCloudGroupsPO selectGroupInfoById(BigDecimal groupId) {
        RongCloudGroupsPO groupsPO = rongCloudGroupsDao.selectById(groupId);
        if (groupsPO == null) {
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_NOT_EXIST, "该群组不存在！");
        }
        return groupsPO;
    }

    @Override
    public RongCloudGroupsPO wholeCreateGroups(GroupsCreateDTO groupsCreateDTO) {
        // 当前用户账号（创建者（群主））
        String userAccount = groupsCreateDTO.getUserAccount();
        // 群成员ID (包含群主)
        List<String> memberAccountList = handlerGroupMemberList(groupsCreateDTO.getMemberAccounts(), userAccount, true);
        // 人员数不能超过限制
        if (memberAccountList.size() >= RongCloudConstant.Groups.MAX_MEMBER_COUNT) {
            throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "群组成员人数不能超过" + RongCloudConstant.Groups.MAX_MEMBER_COUNT + "人！");
        }
        // 群名称
        String groupName = groupsCreateDTO.getName();
        boolean nameFlag = true;
        if (StringUtils.isBlank(groupName)) {
            // 群名称如果为空，则以群成员的名称当做默认群名称
            nameFlag = false;
            groupName = initName(memberAccountList);
        } else {
            // 群名称长度不能太长
            if (isOutOfRange(groupName, 64)) {
                throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "群名称的长度不能超过64字节！");
            }
        }
        // 群头像
        String portraitUri = groupsCreateDTO.getPortraitUri();
        boolean portraitFlag = true;
        if (StringUtils.isBlank(portraitUri)) {
            // 群头像如果为空，则以群成员的头像制作成九宫格当做群头像
            portraitFlag = false;
            portraitUri = initPortraitUri(memberAccountList);
        }
        // 创建群组
        RongCloudGroupsPO groupsPO = new RongCloudGroupsPO();
        groupsPO.setName(groupName);
        groupsPO.setNameFlag(nameFlag);
        groupsPO.setPortraitUri(portraitUri);
        groupsPO.setPortraitFlag(portraitFlag);
        groupsPO.setMemberCount(memberAccountList.size());
        groupsPO.setMaxMemberCount(RongCloudConstant.Groups.MAX_MEMBER_COUNT);
        groupsPO.setCreatorAccount(userAccount);
        groupsPO.setCreateTime(new Date());
        groupsPO.setUpdateTime(new Date());
        int row = rongCloudGroupsDao.insert(groupsPO);
        if (row == 0) {
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_OPERATE_FAIL, "群组创建失败！");
        }
        // 创建群成员
        Result result = null;
        try {
            GroupModel groupModel = initGroupModel(String.valueOf(groupsPO.getId()), memberAccountList, groupName);
            result = rongCloud.group.create(groupModel);
        } catch (Exception e) {
            LOGGER.error("调用融云接口创建群成员异常", e);
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_OPERATE_FAIL, "群组创建失败！请确保融云API可用！");
        }
        if (result != null) {
            if (result.getCode() != null && result.getCode() == RongCloudConstant.Code.SUCCESS) {
                // 保存群成员
                rongCloudGroupMemberService.wholeSaveMembers(groupsPO.getId(), memberAccountList, userAccount);
                /*//发送群消息
                GroupsCreateRename groupsCreateRename = new GroupsCreateRename(userId,nickName(userId),groupName,String.valueOf(entity.getId()));
                String data = JSONObject.toJSONString(groupsCreateRename);
                sendGroupsMessages(userId,String.valueOf(entity.getId()),GROUP_OPERATION_CREATE,data,"创建群组","","","");*/
            } else {
                throw new BusinessException(CodeConstant.RongCloud.GROUPS_OPERATE_FAIL, "群组创建失败！响应码为：" + result.getCode());
            }
        } else {
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_OPERATE_FAIL, "群组创建失败！API未响应！");
        }
        return groupsPO;
    }

    @Override
    public void wholeAdd(GroupsAddDTO groupsAddDTO) {
        // 当前账号
        String userAccount = groupsAddDTO.getUserAccount();
        // 群组ID
        BigDecimal groupId = groupsAddDTO.getGroupId();
        // 这里没有要求一定是群主才能加人，但要去该用户必须是群成员才能加人
        Integer role = rongCloudGroupMemberService.selectRole(userAccount, groupId);
        if (role == null) {
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_REJECT_OPERATION, "你不在该群组中，不可邀请添加群成员！");
        }
        // 添加群成员
        joinMember(groupId, groupsAddDTO.getAddMemberAccounts());
    }

    @Override
    public void wholeJoin(GroupsJoinDTO groupsJoinDTO) {
        // 需要添加的账号
        String toBeAddAccount = groupsJoinDTO.getToBeAddAccount();
        // 群组ID
        BigDecimal groupId = groupsJoinDTO.getGroupId();
        //用户已存在于数组中
        RongCloudGroupMemberPO memberPO = rongCloudGroupMemberDao.selectByMemberAccountAndGroupsId(toBeAddAccount, groupId);
        if (memberPO != null) {
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_ALREADY_EXIST, "你已经在群组中，无需再申请加入");
        }
        // 添加群成员
        List<String> memberAccounts = new ArrayList<>();
        memberAccounts.add(toBeAddAccount);
        joinMember(groupId, memberAccounts);
    }

    @Override
    public void wholeKick(GroupsKickDTO groupsKickDTO) {
        BigDecimal groupId = groupsKickDTO.getGroupId();
        String userAccount = groupsKickDTO.getUserAccount();
        List<String> deleteMemberAccounts = groupsKickDTO.getDeleteMemberAccounts();
        // 群组
        RongCloudGroupsPO groupsPO = this.selectGroupInfoById(groupId);
        // 必需是群主才能操作
        Integer role = rongCloudGroupMemberService.selectRole(userAccount, groupId);
        if (role == null || role != RongCloudConstant.Groups.Role.OWNER) {
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_REJECT_OPERATION, "只有群主才有权限操作！");
        }
        // 处理要踢出的账号集合（去掉重复的，去掉群主的）
        List<String> memberAccountList = handlerGroupMemberList(deleteMemberAccounts, userAccount, false);
        if (CollectionUtils.isEmpty(memberAccountList)) {
            throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "请指定要移除的群成员（不包括群主）！");
        }
        // 操作融云API, 并且更改群组信息
        kickAndQuit(groupsPO, groupId, memberAccountList);

        /*//先发送群组消息
        //获得要踢出的用户对应的昵称
        List<String> kickMemberDisplayName = new ArrayList<>();
        for(String id : kickMemberIds){
            kickMemberDisplayName.add(nickName(id));
        }
        GroupsAddKick groupsAddKick = new GroupsAddKick(nickName(userId),kickMemberIds,kickMemberDisplayName,groupIdStr);
        String data = JSONObject.toJSONString(groupsAddKick);
        sendGroupsMessages(userId,groupIdStr,GROUP_OPERATION_KICKED,data,"移出群成员","","","");*/
    }

    @Override
    public void wholeQuit(GroupsDTO groupsDTO) {
        BigDecimal groupId = groupsDTO.getGroupId();
        String userAccount = groupsDTO.getUserAccount();
        RongCloudGroupsPO groupsPO = rongCloudGroupsDao.selectById(groupId);
        if (groupsPO == null) {
            // 既然都要退出了，群组存不存在都无所谓了，直接返回成功退出
            return;
        }
        // 如果userId是群主
        Integer role = rongCloudGroupMemberService.selectRole(userAccount, groupId);
        if (role != null && role == RongCloudConstant.Groups.Role.OWNER) {
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_REJECT_OPERATION, "群主不能退出群组！");
        }
        // 退出群组的群成员账号
        List<String> quitMemberIds = new ArrayList<>();
        quitMemberIds.add(userAccount);
        // 昵称
        String nickname = nickName(userAccount);
        // 退出群组的成员的昵称集合
        List<String> quitMemberIdDispalyNames = new ArrayList<>();
        quitMemberIdDispalyNames.add(nickname);
        GroupsQuit groupsQuit = new GroupsQuit(nickname, quitMemberIds, quitMemberIdDispalyNames, null, groupId.toString());
        // 发送某某某退出群组的消息
        sendGroupsMessages(userAccount, groupId.toString(), RongCloudConstant.Groups.GROUP_OPERATION_QUIT, JSONObject.toJSONString(groupsQuit),
                "退出群组", "", "", "");
        // 操作融云API, 并且更改群组信息
        kickAndQuit(groupsPO, groupId, quitMemberIds);
    }

    @Override
    public void wholeModifyGroups(GroupsModifyDTO groupsModifyDTO) {
        String userAccount = groupsModifyDTO.getUserAccount();
        BigDecimal groupId = groupsModifyDTO.getGroupId();
        String groupName = groupsModifyDTO.getGroupName();
        // 群组名长度不能超过64字节
        if (StringUtils.isNotBlank(groupName)) {
            if (isOutOfRange(groupName, 64)) {
                throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "群组名字长度不能超过64字节");
            }
        }
        // 群组信息
        RongCloudGroupsPO groupsPO = this.selectGroupInfoById(groupId);
        // 判断当前账号是否再群里
        Integer role = rongCloudGroupMemberService.selectRole(userAccount, groupId);
        if (role == null) {
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_NOT_EXIST, "你不在该群组中,不可操作！");
        }
        // 群昵称
        if (StringUtils.isNotBlank(groupName)) {
            groupsPO.setName(groupName);
            // 用户手动修改了名称，后续就不需要通过人员的数量变更来修改群名称了。
            groupsPO.setNameFlag(true);
        }
        // 群公告
        groupsPO.setBulletin(groupsModifyDTO.getBulletin());
        // 群头像
        String portraitUri = groupsModifyDTO.getPortraitUri();
        if (StringUtils.isNotBlank(portraitUri)) {
            groupsPO.setPortraitUri(portraitUri);
            // 用户手动修改了群头像，后续就不需要通过人员的数量变更来修改群头像了。
            groupsPO.setPortraitFlag(true);
        }
        groupsPO.setUpdateTime(new Date());
        rongCloudGroupsDao.update(groupsPO);
        /*//发送群组消息
            GroupsCreateRename groupsCreateRename = new GroupsCreateRename(userId,nickName(userId),"\""+name+"\"",groupIdStr);
            String data = JSONObject.toJSONString(groupsCreateRename);
            sendGroupsMessages(userId,groupIdStr,GROUP_OPERATION_RENAME,data,"修改群名称","","","");*/
    }

    @Override
    public void wholeModifyDisplayName(GroupsDisplayNameDTO groupsDisplayNameDTO) {
        String displayName = groupsDisplayNameDTO.getDisplayName().trim();
        if (isOutOfRange(displayName, 32)) {
            throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "群名片长度不能超过32字节");
        }
        if (CheckStringUtil.containsEmoji(displayName)) {
            throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "群名片不能包含emoji表情");
        }
        BigDecimal groupId = groupsDisplayNameDTO.getGroupId();
        RongCloudGroupsPO groupsPO = rongCloudGroupsDao.selectById(groupId);
        if (groupsPO == null) {
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_NOT_EXIST, "群组不存在！");
        }
        // 这里没有限制一定要管理员才能更改群名片
        String userAccount = groupsDisplayNameDTO.getUserAccount();
        Integer role = rongCloudGroupMemberService.selectRole(userAccount, groupId);
        if (role == null) {
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_REJECT_OPERATION, "你不存在该群组中，不能更改群名片！");
        }
        // 修改备注
        RongCloudGroupMemberPO queryMemberPO = new RongCloudGroupMemberPO();
        queryMemberPO.setMemberAccount(userAccount);
        queryMemberPO.setGroupId(groupId);
        queryMemberPO.setDisplayName(displayName);
        rongCloudGroupMemberDao.updateByMemberAccountAndGroupId(queryMemberPO);
    }

    @Override
    public List<RongCloudGroupsPO> getGroupList(String userAccount) {
        return rongCloudGroupsDao.selectGroupListByUserAccount(userAccount);
    }

    @Override
    public List<RongCloudGroupMemberPO> getMemberList(BigDecimal groupId) {
        RongCloudGroupsPO groupsPO = rongCloudGroupsDao.selectById(groupId);
        if (groupsPO == null) {
            throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "该数组不存在！");
        }
        Map<String, Object> params = new HashMap<>(1);
        params.put("groupId", groupId);
        return rongCloudGroupMemberDao.selectList(params);
    }

    @Override
    public void wholeDismiss(String userAccount, BigDecimal groupId) {
        // 群需要存在
        this.selectGroupInfoById(groupId);
        // 必需是群主才能解散
        Integer role = rongCloudGroupMemberService.selectRole(userAccount, groupId);
        if (role == null) {
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_REJECT_OPERATION, "你不在该群组中, 不能操作！");
        }
        if (role != RongCloudConstant.Groups.Role.OWNER) {
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_REJECT_OPERATION, "非群主，无权限操作");
        }
        Result result;
        List<String> memberIds = new ArrayList<>();
        memberIds.add(userAccount);
        // 需要先发送消息（如果先解散群的话，则无法把解散群的消息都通知给群里面的成员）
        GroupsDismiss groupsDismiss = new GroupsDismiss(nickName(userAccount), groupId.toString());
        sendGroupsMessages(userAccount, groupId.toString(), RongCloudConstant.Groups.GROUP_OPERATION_DISMISS,
                JSONObject.toJSONString(groupsDismiss), "解散群组", "", "", "");
        // 再操作融云
        try {
            GroupModel groupModel = initGroupModel(groupId.toString(), memberIds, "");
            result = rongCloud.group.dismiss(groupModel);
        } catch (Exception e) {
            LOGGER.error("调用融云解散群组的方法失败", e);
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_OPERATE_FAIL, "解散群组失败！请确保API可用！");
        }
        if (result != null && result.getCode() != null && result.getCode() == RongCloudConstant.Code.SUCCESS) {
            // 解散成功，删除群
            rongCloudGroupsDao.deleteById(groupId);
            // 删除群成员
            rongCloudGroupMemberDao.deleteByGroupId(groupId);
        } else {
            String msg = result != null ? "响应码：" + result.getCode() : "";
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_OPERATE_FAIL, "解散群组失败！" + msg);
        }
    }

    /**
     * 通过融云发送系统信息，详见https://www.rongcloud.cn/docs/message_architecture.html#group_notification_message
     *
     * @param senderId       发送人
     * @param memberIds      接收人（数组）
     * @param operatorUserId 操作人
     * @param operation      操作的行为，比如踢人
     * @param data           群组中各种通知的操作数据
     * @param message        消息内容
     * @param extra          扩展信息
     */
    private void sendSystemMessage(String senderId, List<String> memberIds, String operatorUserId, String operation, String data, String message, String pushContent, String pushData, String extra) {
        String[] targetIds = memberIds.toArray(new String[memberIds.size()]);
        GroupNtfMessage groupNtfMessage = new GroupNtfMessage(operatorUserId, operation, data, message, extra);
        RongCloudUtil.sendSystemMessage(senderId, targetIds, groupNtfMessage, pushContent, pushData);
    }

    /**
     * 发送群组消息
     */
    private void sendGroupsMessages(String fromUserId, String toGroupId, String operation, String data, String message, String pushContent, String pushData, String extra) {
        GroupNtfMessage groupNtfMessage = new GroupNtfMessage(fromUserId, operation, data, message, extra);
        RongCloudUtil.sendGroupMessage(fromUserId, toGroupId, groupNtfMessage, pushContent, pushData);
    }

    /**
     * 生成九宫格头像
     *
     * @param memberAccountList 成员账号
     * @return 头像完整路径
     * @author whysu @2021-03-17 11:02
     */
    private String initPortraitUri(List<String> memberAccountList) {
        List<String> picUrls = new ArrayList<>();
        int i = 0;
        for (String memberAccount : memberAccountList) {
            RongCloudUserPO userPO = rongCloudUserDao.selectByAccount(memberAccount);
            if (userPO != null && StringUtils.isNotBlank(userPO.getAvatar())) {
                picUrls.add(userPO.getAvatar());
                i++;
                if (i >= 9) {
                    break;
                }
            }
        }
        try {
            // 生成九宫格群组头像
            byte[] buff = ImageUtil.getCombinationOfhead(picUrls);
            //上传到FastDFS
            String url = dfsClient.uploadFile(buff, "jpg");
            if (!Objects.equals(url, "")) {
                return fileRoot + "/" + url;
            }
        } catch (Exception e) {
            LOGGER.error("生成九宫格群组头像发生异常", e);
        }
        return ConfigConstant.defaultImage;
    }

    /**
     * 群名称未设置的情况下，设定临时的群名称
     *
     * @param memberIds 群成员ID
     * @return 群名称
     */
    private String initName(List<String> memberIds) {
        //输出形如：  张三、李四、王五、赵钱 (4)
        //前面显示昵称，最多四个，括号中是 群成员个数
        StringBuilder groupName = new StringBuilder();
        StringBuilder temp = new StringBuilder();
        int num = 0;
        for (String memberId : memberIds) {
            num++;
            String nickname = nickName(memberId);
            temp.append(nickname).append("、");
            //融云限制的群名称长度是64,这里限制下为54保证不会出错
            if (isOutOfRange(String.valueOf(temp), 54)) {
                break;
            }
            //如果temp长度超了，那么grouName就不再添加，这样就不会超了
            groupName.append(nickname).append("、");
            //最多以4个用户的昵称作为群名
            if (num > 4) {
                break;
            }
        }
        if (groupName.length() > 0) {
            groupName = new StringBuilder(groupName.substring(0, groupName.length() - 1));
        } else {
            groupName.append("群聊");
        }
        //去掉前后空格
        String name = String.valueOf(groupName).trim();
        return name + " (" + memberIds.size() + ")";
    }

    /**
     * 查询用户账号的昵称
     *
     * @param userAccount 用户账号
     * @return 昵称
     * @author whysu @2021-03-16 20:59
     */
    private String nickName(String userAccount) {
        RongCloudUserPO rongCloudUserPO = rongCloudUserDao.selectByAccount(userAccount);
        if (rongCloudUserPO != null && StringUtils.isNotBlank(rongCloudUserPO.getNickname())) {
            return rongCloudUserPO.getNickname();
        } else {
            return userAccount;
        }
    }

    /**
     * String的字节数 是否超过 xx 字节
     */
    private boolean isOutOfRange(String str, int len) {
        try {
            if (str.getBytes("utf-8").length > len) {
                return true;
            }
        } catch (Exception e) {
            LOGGER.error("解析异常，入参：{}", str);
        }
        return false;
    }

    /**
     * 初始化GroupModel
     *
     * @param groupId   群id
     * @param memberIds 群成员id
     * @param groupName 群名称
     */
    private GroupModel initGroupModel(String groupId, List<String> memberIds, String groupName) {
        GroupMember[] members = new GroupMember[memberIds.size()];
        for (int i = 0; i < memberIds.size(); i++) {
            members[i] = new GroupMember().setId(memberIds.get(i));
        }
        return new GroupModel()
                .setId(groupId)
                .setMembers(members)
                .setName(groupName);
    }

    /**
     * 处理群组成员账号集合
     *
     * @param memberAccounts     前端传来的成员列表
     * @param creatorAccount     管理员账号
     * @param containCreatorFlag 是否包含群主，true包含，false不包含
     * @return 处理后的账号集合
     * @author whysu @2021-03-16 13:40
     */
    private List<String> handlerGroupMemberList(List<String> memberAccounts, String creatorAccount, boolean containCreatorFlag) {
        if (CollectionUtils.isEmpty(memberAccounts)) {
            throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "请指定成员！");
        }
        if (StringUtils.isBlank(creatorAccount)) {
            throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "群主账号不能为空！");
        }
        // 处理后的群组成员账号集合
        List<String> newMemberAccounts = new ArrayList<>();
        // 如果包含群主
        if (containCreatorFlag) {
            newMemberAccounts.add(creatorAccount);
        }
        // 使用Set的特性过滤重复账号
        Set<String> accountSet = new HashSet<>();
        memberAccounts.forEach(it -> {
            // 过滤重复账号
            if (!accountSet.add(it)) {
                return;
            }
            // 如果不包含群主的话，需要过滤掉
            if (!containCreatorFlag && it.equals(creatorAccount)) {
                return;
            }
            newMemberAccounts.add(it);
        });
        return newMemberAccounts;
    }


    /**
     * 添加群成员(/add和/join 其实调用的是同一方法)
     *
     * @param groupId               群组id
     * @param toBeAddMemberAccounts 要增加的成员账号集合
     */
    private void joinMember(BigDecimal groupId, List<String> toBeAddMemberAccounts) {
        if (CollectionUtils.isEmpty(toBeAddMemberAccounts)) {
            throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "请指定要添加进群组的账号！");
        }
        // 群组
        RongCloudGroupsPO groupsPO = this.selectGroupInfoById(groupId);
        if ((groupsPO.getMemberCount() + toBeAddMemberAccounts.size()) > groupsPO.getMaxMemberCount()) {
            throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "群成员人数最大为" + groupsPO.getMaxMemberCount() + "人！");
        }
        Result result;
        try {
            GroupModel groupModel = initGroupModel(String.valueOf(groupId), toBeAddMemberAccounts, groupsPO.getName());
            result = rongCloud.group.join(groupModel);
        } catch (Exception e) {
            LOGGER.error("调用融云接口添加群成员异常", e);
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_OPERATE_FAIL, "群组添加人员失败！请确保融云API可用！");
        }
        if (result != null) {
            if (result.getCode() != null && result.getCode() == RongCloudConstant.Code.SUCCESS) {
                // 保存成员
                rongCloudGroupMemberService.wholeSaveMembers(groupId, toBeAddMemberAccounts, null);
                // 更新群组的人员总数+头像+名称
                handlerGroupsInfo(groupId);
            } else {
                throw new BusinessException(CodeConstant.RongCloud.GROUPS_OPERATE_FAIL, "群组添加人员失败！响应码：" + result.getCode());
            }
        } else {
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_OPERATE_FAIL, "群组添加人员失败！API未响应！");
        }

    }

    /**
     * 人员如果有变化的话，更新群阻的人员个数。如果头像或者名称不是自定义的话，需要根据人员变化而更改。
     *
     * @param groupId 群组ID
     * @author whysu @2021-03-16 14:57
     */
    private void handlerGroupsInfo(BigDecimal groupId) {
        // 修改本地数据库的 群组的 信息
        RongCloudGroupsPO groupsPO = rongCloudGroupsDao.selectById(groupId);
        if (groupsPO == null) {
            LOGGER.error("群组不存在，groupId: {}", groupId);
            return;
        }
        // 查询该群当前有多少人
        Map<String, Object> params = new HashMap<>();
        params.put("groupId", groupId);
        List<RongCloudGroupMemberPO> oldMemberList = rongCloudGroupMemberDao.selectList(params);
        if (CollectionUtils.isNotEmpty(oldMemberList)) {
            // 人员数未变的话，则无需修改
            if (groupsPO.getMemberCount() == oldMemberList.size()) {
                return;
            }
            if (!groupsPO.getNameFlag() || !groupsPO.getPortraitFlag()) {
                List<String> ids = new ArrayList<>();
                for (RongCloudGroupMemberPO po : oldMemberList) {
                    ids.add(String.valueOf(po.getMemberAccount()));
                }
                // 群名称未自定义，则根据前4位成员更新群名称
                if (!groupsPO.getNameFlag()) {
                    groupsPO.setName(initName(ids));
                }
                // 群头像未自定义，则根据前9位成员更新群头像
                if (!groupsPO.getPortraitFlag()) {
                    groupsPO.setPortraitUri(initPortraitUri(ids));
                }
            }
            groupsPO.setMemberCount(oldMemberList.size());
            groupsPO.setUpdateTime(new Date());
            rongCloudGroupsDao.update(groupsPO);
        } else {
            LOGGER.error("群组当前没有一个人了！groupId: {}", groupId);
        }
    }

    /**
     * 移除群成员（/kick和/quit其实调用的是同一个方法）
     *
     * @param oldGroup             未踢人之前的群组信息
     * @param groupId              群主id
     * @param deleteMemberAccounts 需要移除的账号集合
     */
    private void kickAndQuit(RongCloudGroupsPO oldGroup, BigDecimal groupId, List<String> deleteMemberAccounts) {
        Result result;
        try {
            // 调用融云API
            GroupModel groupModel = initGroupModel(String.valueOf(groupId), deleteMemberAccounts, oldGroup.getName());
            result = rongCloud.group.quit(groupModel);
        } catch (Exception e) {
            LOGGER.error("调用融云API退出群组失败！", e);
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_OPERATE_FAIL, "操作失败！请确保API可用！");
        }
        if (result != null && result.getCode() != null && result.getCode() == RongCloudConstant.Code.SUCCESS) {
            // 移除成功，改变本地数据库
            rongCloudGroupMemberDao.deleteByMemberListAndGroupId(deleteMemberAccounts, groupId);
            // 修改群组信息
            oldGroup.setMemberCount(oldGroup.getMemberCount() - deleteMemberAccounts.size());
            // 更新群名称
            List<String> accountList = new ArrayList<>();
            if (!oldGroup.getNameFlag() || !oldGroup.getPortraitFlag()) {
                // 查询当前该群组有多少人
                Map<String, Object> params = new HashMap<>();
                params.put("groupId", groupId);
                List<RongCloudGroupMemberPO> currentMembers = rongCloudGroupMemberDao.selectList(params);
                if (CollectionUtils.isNotEmpty(currentMembers)) {
                    currentMembers.forEach(it -> {
                        accountList.add(it.getMemberAccount());
                    });
                }
                // 更新群名称
                if (!oldGroup.getNameFlag()) {
                    oldGroup.setName(initName(accountList));
                }
                // 更新群头像
                if (!oldGroup.getPortraitFlag()) {
                    oldGroup.setPortraitUri(initPortraitUri(accountList));
                }
            }
            oldGroup.setUpdateTime(new Date());
            rongCloudGroupsDao.update(oldGroup);
        } else {
            LOGGER.error("调用融云kick方法异常, 响应码：{}", result != null ? result.getCode() : "");
            throw new BusinessException(CodeConstant.RongCloud.GROUPS_OPERATE_FAIL, "操作失败！");
        }
    }
}
